﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using FxCopContrib.TestHarness;
using System.Text.RegularExpressions;

namespace FxCopContrib.Tests
{
    [TestClass]
    public class RegularExpressionDoesNotCompileTests
    {
        [TestMethod]
        public void RuleWillTriggerIfIncorrectRegexIsPassedToStaticIsMatchDirectly()
        {
            FxCopTest
                .ForRule<RegularExpressionDoesNotCompile>()
                .OnMethod(
                    @"
                        public void TestMethod()
                        {
                            Regex.IsMatch("""", ""[a-z]*+"");
                        }
                    ",
                    typeof(Regex).Namespace
                )
                .WithReferencesTo(typeof(Regex), typeof(string))
                .WillFind(ProblemPrototype.Default)
                .Conclusive()
                .Verify();
        }

        [TestMethod]
        public void RuleWillTriggerIfIncorrectRegexIsPassedConstructorDirectly()
        {
            FxCopTest
                .ForRule<RegularExpressionDoesNotCompile>()
                .OnMethod(
                    @"
                        public void TestMethod()
                        {
                            new Regex(""[a-z]*+"");
                        }
                    ",
                    typeof(Regex).Namespace
                )
                .WithReferencesTo(typeof(Regex), typeof(string))
                .WillFind(ProblemPrototype.Default)
                .Conclusive()
                .Verify();
        }

        [TestMethod]
        public void RuleWillTriggerIfIncorrectRegexIsPassedFromALocalVariable()
        {
            FxCopTest.ForRule<RegularExpressionDoesNotCompile>()
                .OnMethod(
                    @"
                        public void TestMethod()
                        {
                            string expression = ""[a-z]*+"";
                            new Regex(expression);
                        }
                    ",
                    typeof(Regex).Namespace
                )
                .WithReferencesTo(typeof(Regex), typeof(string))
                .WillFind(ProblemPrototype.Default)
                .Conclusive()
                .Verify();
        }

        [TestMethod]
        public void RuleWillTriggerIfIncorrectRegexIsPassedFromAConstField()
        {
            FxCopTest
                .ForRule<RegularExpressionDoesNotCompile>()
                .OnMethod(
                    @"
                        private const string expression = ""[a-z]*+"";

                        public void TestMethod()
                        {
                            new Regex(expression);
                        }
                    ",
                    typeof(Regex).Namespace
                )
                .WithReferencesTo(typeof(Regex), typeof(string))
                .WillFind(ProblemPrototype.Default)
                .Conclusive()
                .Verify();
        }



        [TestMethod]
        public void RuleWillTriggerIfIncorrectRegexIsPassedFromAReadOnlyField()
        {
            FxCopTest
                .ForRule<RegularExpressionDoesNotCompile>()
                .OnMethod(
                @"
                    private readonly string expression = ""[a-z]*+"";

                    public void TestMethod()
                    {
                        new Regex(expression);
                    }
                ",
                typeof(Regex).Namespace
            )
            .WithReferencesTo(typeof(Regex), typeof(string))
            .WillFind(ProblemPrototype.Default)
            .Conclusive()
            .Verify();
        }

        [TestMethod]
        public void RuleWillTriggerIfIncorrectRegexIsPassedFromAReadOnlyFieldSetInTheConstructor()
        {
            FxCopTest
                .ForRule<RegularExpressionDoesNotCompile>()
                .OnType(
                    @"
                        public class Test
                        {
                            private readonly string expression;

                            public Test()
                            {
                                 expression = ""[a-z]*+"";
                            }

                            public void TestMethod()
                            {
                                new Regex(expression);
                            }
                        }
                    ",
                    typeof(Regex).Namespace
                )
                .WithReferencesTo(typeof(Regex), typeof(string))
                .WillFind(ProblemPrototype.Default)
                .Conclusive()
                .Verify();
        }

        [TestMethod]
        public void RuleWillTriggerIfIncorrectRegexIsPassedFromAReadOnlyFieldSetInTheStaticConstructor()
        {
            FxCopTest
                .ForRule<RegularExpressionDoesNotCompile>()
                .OnType(
                @"
                    public class Test
                    {
                        private static readonly string expression;

                        static Test()
                        {
                             expression = ""[a-z]*+"";
                        }

                        public void TestMethod()
                        {
                            new Regex(expression);
                        }
                    }
                ",
                    typeof(Regex).Namespace
                )
                .WithReferencesTo(typeof(Regex), typeof(string))
                .WillFind(ProblemPrototype.Default)
                .Conclusive()
                .Verify();
        }

        [TestMethod]
        public void RuleWillFlagUnknownRegexOptions()
        {
            FxCopTest
                .ForRule<RegularExpressionDoesNotCompile>()
                .OnMethod(
                    @"
                        public void TestMethod()
                        {
                            Regex.Match("""", ""a+"", (RegexOptions)123456);
                        }
                    ",
                    typeof(Regex).Namespace
                )
                .WithReferencesTo(typeof(Regex), typeof(RegexOptions))
                .WillFind(ProblemPrototype.WithResulutionName("UnknownRegexOptions"))
                .Conclusive()
                .Verify();
        }

        [TestMethod]
        public void RuleWillFlagInvalidRegexOptions()
        {
            FxCopTest
                .ForRule<RegularExpressionDoesNotCompile>()
                .OnMethod(
                    @"
                        public void TestMethod()
                        {
                            Regex.Match("""", ""a+"", RegexOptions.ExplicitCapture | RegexOptions.ECMAScript);
                        }
                    ",
                    typeof(Regex).Namespace
                )
                .WithReferencesTo(typeof(Regex), typeof(RegexOptions))
                .WillFind(ProblemPrototype.WithResulutionName("InvalidRegexOptions"))
                .Conclusive()
                .Verify();
        }
    }
}
